package com.jushu.storbox.service;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import android.content.Context;
import android.util.Log;

import com.jushu.storbox.ShareDriveApplication;
import com.jushu.storbox.constant.Constant;
import com.jushu.storbox.database.DAOFactory;
import com.jushu.storbox.entities.FileInfo;
import com.jushu.storbox.entities.FolderInfo;
import com.jushu.storbox.filesystem.FileManagerFactory;
import com.jushu.storbox.filesystem.iFileManager;
import com.jushu.storbox.util.CollectionUtils;
import com.jushu.storbox.util.DirectoryUtil;
import com.jushu.storbox.util.LogUtil;
import com.huawei.sharedrive.sdk.android.exception.ClientException;
import com.huawei.sharedrive.sdk.android.modelV2.response.FileInfoResponseV2;
import com.huawei.sharedrive.sdk.android.modelV2.response.FolderResponse;
import com.huawei.sharedrive.sdk.android.serviceV2.FileClientV2;

public class FileSyncComparator {

	public static void syncFolderToLocal(Context context,
			List<FolderResponse> serverList, List<FolderInfo> clientList,
			String ownerId, String folderId) {
		if (CollectionUtils.isEmpty(serverList)
				&& CollectionUtils.isEmpty(clientList)) {
			return;
		}
		Collections.sort(serverList, new Comparator<FolderResponse>() {
			public int compare(FolderResponse arg0, FolderResponse arg1) {
				return Long.valueOf(arg0.getId()).compareTo(
						Long.valueOf(arg1.getId()));
			}
		});

		FolderInfo parentFolder = DAOFactory.instance(context).getFolderDao()
				.getFolderById(ownerId, folderId);

		for (FolderResponse frServer : serverList) {
			boolean isFolderUpdate = false;
			FolderInfo currentFolder = null;
			for (FolderInfo localFolder : clientList) {
				if (!frServer.getId().equals(localFolder.getId())) {
					continue;
				}
				currentFolder = localFolder;
				if (!frServer.getName().equals(localFolder.getName())) {
					isFolderUpdate = true;
					break;
				}
				if (frServer.getModifiedAt() != localFolder.getModifiedAt()) {
					isFolderUpdate = true;
					break;
				}
				break;
			}
			if (isFolderUpdate) {
				// isChange = true;
				DAOFactory.instance(context).getFolderDao()
						.updateFolder(frServer);
			}
			if (currentFolder == null) {
				FolderInfo local = DAOFactory.instance(context).getFolderDao()
						.getFolderById(frServer);
				if (local == null) {
					DAOFactory.instance(context).getFolderDao()
							.insertFolder(frServer, 0);
				} else {
					DAOFactory.instance(context).getFolderDao()
							.updateFolder(frServer);
				}
				// DAOFactory.instance(context).getFolderDao().insertOrUpdateFolder(frServer,
				// context);
			}

			if (parentFolder != null && parentFolder.isSync()) {
				DAOFactory
						.instance(context)
						.getFileDao()
						.updateSyncStatus(frServer.getOwnerBy(), frServer.getId(),Constant.DOWNLOAD_STATUS_CACHE_DB );
			}
		}

		for (FolderInfo localFolder : clientList) {
			boolean isExist = false;
			for (FolderResponse frServer : serverList) {
				if (frServer.getId().equals(localFolder.getId())) {
					isExist = true;
					break;
				}
			}
			if (!isExist) {
				ServiceFactory.instance(context).getLocalFolderService()
						.deleteFolderAndChild(localFolder);
			}
		}
	}

	public static void syncFileToLocal(Context context,
			List<FileInfoResponseV2> serverList, List<FileInfo> clientList,
			String ownerId, String folderId) {
		if (CollectionUtils.isEmpty(serverList)
				&& CollectionUtils.isEmpty(clientList)) {
			return;
		}
		boolean fileContentIsChanged = false;
		boolean nameIsUpdate = false;
		boolean isFileUpate = false;
		String oldFilePath = null;
		String newFilePath = null;

		Collections.sort(serverList, new Comparator<FileInfoResponseV2>() {
			public int compare(FileInfoResponseV2 arg0, FileInfoResponseV2 arg1) {
				return Long.valueOf(arg0.getId()).compareTo(
						Long.valueOf(arg1.getId()));
			}
		});

		FolderInfo folder = DAOFactory.instance(context).getFolderDao()
				.getFolderById(ownerId, folderId);

		iFileManager mdmTools = FileManagerFactory.getFileManager(context);
		for (FileInfoResponseV2 frServer : serverList) {
			fileContentIsChanged = false;
			nameIsUpdate = false;
			isFileUpate = false;
			FileInfo currentFile = null;
			for (FileInfo localFile : clientList) {
				if (!frServer.getId().equals(localFile.getId())) {
					continue;
				}
				currentFile = localFile;
				if (!frServer.getName().equals(localFile.getName())) {
					isFileUpate = true;
					nameIsUpdate = true;
					oldFilePath = DirectoryUtil.generateFileDownloadPath(
							context, localFile.getOwnerBy(), localFile.getId(), localFile.getName());
				}
				if (!fileContentEquals(frServer, localFile)) {
					isFileUpate = true;
					if (localFile.isSync()) {
						fileContentIsChanged = true;
					}
					oldFilePath = DirectoryUtil.generateFileDownloadPath(
							context, localFile.getOwnerBy(), localFile.getId(), localFile.getName());
				}
				if (frServer.getModifiedAt() != localFile.getModifiedAt()) {
					isFileUpate = true;
				}
				break;
			}

			if (isFileUpate) {
				LogUtil.i("~~", "server update file item" + frServer.getName());
				DAOFactory.instance(context).getFileDao()
						.updateFile(frServer, false, false);
				if (fileContentIsChanged) {
					LogUtil.i(
							"~~",
							"server update file content"
									+ currentFile.getName());
					mdmTools.deleteFile(oldFilePath);
					DirectoryUtil.deleteFileThumbnailPath(context,
							currentFile.getOwnerBy(), currentFile.getId(),
							currentFile.getName());
					DAOFactory
							.instance(context)
							.getFileDao()
							.updateTransStatus(currentFile, Constant.DOWNLOAD_NON_UPDATE_DB);
				}
				if (nameIsUpdate) {
					newFilePath = DirectoryUtil.generateFileDownloadPath(
							context, frServer.getOwnerBy(), frServer.getId(), frServer.getName());
					DAOFactory.instance(context).getFileDao()
							.updateLocalPath(frServer, newFilePath);
					LogUtil.i("~~",
							"server update file item'name: old name: "
									+ currentFile.getName() + "new name: "
									+ frServer.getName());

					mdmTools.rename(oldFilePath, newFilePath);
					DirectoryUtil.renameThumbnailFile(context,
							currentFile.getOwnerBy(), currentFile.getId(),
							currentFile.getName(), frServer.getName());
				}

			}
			if (currentFile == null) {
				LogUtil.i("~~",
						"server \"add\" new file item" + frServer.getName());
				FileInfo fileInfo = DAOFactory.instance(context).getFileDao()
						.getFile(frServer);
				if (null != fileInfo) {
					DAOFactory.instance(context).getFileDao()
							.updateFile(frServer, false, false);

					LogUtil.i(
							"~~",
							"server move file item: old-> "
									+ fileInfo.getParent() + "new-> "
									+ frServer.getParent());
					oldFilePath = DirectoryUtil.generateFileDownloadPath(
							context, frServer.getOwnerBy(), fileInfo.getId(), fileInfo.getName());
					newFilePath = DirectoryUtil.generateFileDownloadPath(
							context, frServer.getOwnerBy(), frServer.getId(), frServer.getName());

					if (!fileContentEquals(frServer, fileInfo)) {
						LogUtil.i("~~", "server move and update file content: "
								+ fileInfo.getName());
						mdmTools.deleteFile(oldFilePath);
						DirectoryUtil.deleteFileThumbnailPath(context,
								fileInfo.getOwnerBy(), fileInfo.getId(),
								fileInfo.getName());
						DAOFactory
								.instance(context)
								.getFileDao()
								.updateTransStatus(fileInfo,
										Constant.DOWNLOAD_NON_UPDATE_DB);
					}

					if (!frServer.getName().equals(fileInfo.getName())) {
						DAOFactory.instance(context).getFileDao()
								.updateLocalPath(frServer, newFilePath);
						LogUtil.i("~~",
								"server move and update file item'name: old name: "
										+ fileInfo.getName() + "new name: "
										+ frServer.getName());
						mdmTools.rename(oldFilePath, newFilePath);
						DirectoryUtil.renameThumbnailFile(context,
								fileInfo.getOwnerBy(), fileInfo.getId(),
								fileInfo.getName(), frServer.getName());
					}

				} else {
					LogUtil.i("~~",
							"server add new file item: " + frServer.getName());
					DAOFactory.instance(context).getFileDao()
							.insertFile(frServer);
				}
				if (folder != null && folder.isSync()) {
					DAOFactory
							.instance(context)
							.getFileDao()
							.updateSyncStatus(frServer,
									Constant.DOWNLOAD_STATUS_CACHE_DB);
				}
			}
		}

		for (FileInfo localFile : clientList) {
			boolean isExist = false;
			for (FileInfoResponseV2 frServer : serverList) {
				if (frServer.getId().equals(localFile.getId())) {
					isExist = true;
					break;
				}
			}
			if (!isExist) {
				LogUtil.i("~~", "server delete file item!");
				mdmTools.deleteFile(localFile.getLoctPath());
				DirectoryUtil.deleteFileThumbnailPath(context,
						localFile.getOwnerBy(), localFile.getId(),
						localFile.getName());
				ServiceFactory.instance(context).getLocalFileService()
						.deleteFileVirtual(localFile);
			}
		}
	}

	private static boolean fileContentEquals(FileInfoResponseV2 server,
			FileInfo local) {
		try {
			if (server.getMd5() != null) {
				return server.getMd5().equals(local.getMd5());
			} else {
				return server.getSha1().equals(local.getSha1());
			}
		} catch (Exception e) {
			LogUtil.e("File content compare exception: " + e.getMessage());
		}
		return true;
	}
}
